#include "flash.h"
#include "record.h"
#include "version.h"

#define	SPACE	0xffffffff

typedef struct _PIECE{
	ubyte	v[60];
}PIECE;

static uint *bottom;
static uint	*head;
static uint	lastSteps;
static uint	lastTick;
static uint *top;
static ubyte skip;

static void put(uint value){
	flash_put32(head++,value);
	if(head>=top)
		head=bottom;
	if(*head!=SPACE)
		flash_erasePage(head);
}
static tail(void){
	uint *p=head+1;
	while(*p==SPACE && p<top)
		p++;
	if(p>=top){
		p=bottom;
		while(*p==SPACE && p<head)
			p++;
		if(p>=head)
			return;
	}
	p=(uint*)((uint)p&0xfffffc00);
	uint s=((uint)p-(uint)head)&0x7fff;
	while(s<0x1000){
		flash_erasePage(p);
		p+=0x100;
		s+=0x400;
	}
	flash_put32(p,0);
}

//------------------------------------------------------------------------------

void record_init(uint tick,uint steps){
	flash_begin();
	uint *p=(uint*)version_bottom+1;
	bottom=p;
	top=(uint*)version_bottom+0x7800/sizeof(uint);
	if(*(uint*)version_bottom==SPACE){
        // http://www.douban.com/group/topic/36380279/
		while(*p==SPACE && p<top)
			p++;					// skip space
		while(*p!=SPACE && p<top)
			p++;					// skip data
		if(p>=top)
			p=bottom;
	}else{
		// init record region
		flash_erasePage(p);
		p++;
	}
	flash_put32(p++,0);
	flash_put32(p++,tick);
	head=p;
	tail();
	flash_end();
	lastSteps=steps;
	lastTick=tick;
}
REPORT* record_piece(void){
	static REPORT r={RPT_DATAIMG,0x8000};
	r.versionV+=60;
	if(r.versionV>=0x7800){
		r.versionV=0xffc4;
		return 0;
	}
	PIECE *s=(PIECE*)(version_bottom+r.versionV);
	*(PIECE*)&r.tickLoI=*s;
	return &r;
}
void record_roll(void){
	flash_begin();
	tail();
	flash_end();
}
void record_reset(uint tick,uint steps){
	if(head){
		flash_begin();
		put((steps-lastSteps)<<16);
		put(tick);
		lastTick=tick;
		lastSteps=0;
		skip=0;
		flash_end();
	}
}
void record_save(uint tick,uint steps){
	if(head && (steps!=lastSteps)){
		flash_begin();
		uint t=tick-lastTick;
		uint v=(steps-lastSteps)<<16;
		if(skip){
			t-=600;
			if(t>0xffff || t==0){
				put(0);
				put(tick);
			}else put(t);
			t=600;
			skip=0;
		}
		lastTick=tick;
		lastSteps=steps;
		if(t>0xffff || t==0){
			put(v);
			put(tick);
		}else put(v+t);
		flash_end();
	}else skip=1;
}